﻿#region Header
// Copyright 2007-2011, Jerónimo Milea
// 
// This file is part of NetJsWire.
// 
//     NetJsWire is free software: you can redistribute it and/or modify
//     it under the terms of the GNU General Public License as published by
//     the Free Software Foundation, either version 3 of the License, or
//     (at your option) any later version.
// 
//     NetJsWire is distributed in the hope that it will be useful,
//     but WITHOUT ANY WARRANTY; without even the implied warranty of
//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//     GNU General Public License for more details.
// 
//     You should have received a copy of the GNU General Public License
//     along with NetJsWire.  If not, see <http://www.gnu.org/licenses/>.
#endregion

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Dynamic;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using NetJsWire.Lite.Converters;
using NetJsWire.Lite.Designers;
using NetJsWire.Lite.Interfaces;
using NetJsWire.Lite.Widgets.UI.Form;
using NetJsWire.Lite.Widgets.UI.Layout;
using Newtonsoft.Json;
using System.Linq;

namespace NetJsWire.Lite.Widgets.UI
{
    [JsonObject( MemberSerialization = MemberSerialization.OptIn )]
    [Designer( typeof( BoxComponentDesigner ) )]
    [Designer( typeof( DocumentDesigner ), typeof( IRootDesigner ) )]
    public class BoxComponent : BaseComponent, IDynamicMetaObjectProvider
    {
        private string _anchor;
        private readonly string[] _validRegions = new string[] { "north", "south", "west", "east", "center" };

        public BoxComponent()
            : this( null )
        {
        }

        public BoxComponent( IContainer container )
            : base( container )
        {
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            Xtype = "box";
            // ReSharper restore DoNotCallOverridableMethodsInConstructor
        }

        [JsonProperty( "anchor", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore )]
        [DefaultValue( ( string ) null )]
        [Browsable( true )]
        [Description( "Note: This config is only used when this Component is rendered by a Container which has been configured to use an AnchorLayout (or subclass thereof). based layout manager." )]
        [RefreshProperties( RefreshProperties.Repaint )]
        public new virtual string Anchor
        {
            get { return _anchor; }
            set
            {
                _anchor = value;
                if ( Parent == null ) return;

                Parent.PerformLayout();
                Parent.InvalidateWindow();
            }
        }

        [JsonProperty( "xtype", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Include )]
        [DefaultValue( "box" )]
        [TypeConverter( typeof( XtypeTypeConverter ) )]
        [Description( "The registered xtype to create." )]
        public virtual string Xtype { get; set; }

        [JsonProperty( "width", DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore )]
        [DefaultValue( 0 )]
        public new virtual int Width
        {
            get
            {
                if ( Site == null || !Site.DesignMode )
                {
                    if ( Parent != null && ( Parent is Container && ( ( Container ) Parent ).Layout == LayoutType.Card ) )
                        return 0;

                    if ( Flex != 0 && Parent != null && Parent is CompositeField )
                    {
                        return 0;
                    }
                }
                return base.Width;
            }
            set { base.Width = value; }
        }

        [JsonProperty( "height", DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore )]
        [DefaultValue( 0 )]
        public new virtual int Height
        {
            get
            {
                if ( Site == null || !Site.DesignMode )
                {
                    if ( Parent != null && ( Parent as Container != null ) && ( ( Parent as Container ).Layout == LayoutType.Card || ( Parent as Container ).Layout == LayoutType.Column ) )
                        return 0;
                    //Nunca setear el height de compositefield en el cliente.
                    if ( this is CompositeField || Xtype == "compositefield" )
                        return 0;
                }

                return base.Height;
            }
            set { base.Height = value; }
        }

        [JsonProperty( "x", DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore )]
        [DefaultValue( 0 )]
        [Browsable( false )]
        public virtual int? X
        {
            get
            {
                if ( this is Window /* && Site != null && Site.DesignMode */)
                {
                    return 0;
                }
                if ( Parent != null && Parent is Panel )
                {
                    var p = ( Panel ) Parent;
                    if ( p.Bbar == this )
                        return null;
                }
                return ( Parent != null && Parent is Container && ( ( ( Container ) Parent ).Layout == LayoutType.Absolute || ( ( Container ) Parent ).Layout == LayoutType.Anchor ) ? Left : ( int? ) null );
            }
        }

        [JsonProperty( "y", DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore )]
        [DefaultValue( 0 )]
        [Browsable( false )]
        public virtual int? Y
        {
            get
            {
                if ( this is Window /*&& Site != null && Site.DesignMode*/ )
                {
                    return null;
                }
                if ( Parent != null && Parent is Panel )
                {
                    var p = ( Panel ) Parent;
                    if ( p.Bbar == this )
                        return null;
                }
                return ( Parent != null && Parent is Container && ( ( ( Container ) Parent ).Layout == LayoutType.Absolute || ( ( Container ) Parent ).Layout == LayoutType.Anchor ) ? Top : ( int? ) null );
            }
        }

        private string _region;

        [JsonProperty( "region", DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore )]
        [DefaultValue( ( string ) null )]
        [Browsable( true )]
        [Description( "Note: this config is only used when this BoxComponent is rendered by a Container which has been configured to use the BorderLayout layout manager (e.g. specifying layout:'border')." )]
        public new string Region
        {
            get { return _region; }
            set
            {
                if ( !string.IsNullOrWhiteSpace( value ) )
                {
                    if ( !_validRegions.Any( s => s.Equals( value, StringComparison.OrdinalIgnoreCase ) ) )
                    {
                        MessageBox.Show( value + " is not valid for region.", "Error",
                                                              MessageBoxButtons.OK, MessageBoxIcon.Error );
                        return;
                    }
                }
                _region = value;
                if ( string.IsNullOrWhiteSpace( value ) )
                {
                    _region = null;
                }
                if ( Parent != null )
                {
                    Parent.PerformLayout();
                    Parent.Invalidate( true );
                }
            }
        }
    }
}
